home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / src / xad_bzip.lha / bzip.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-06  |  15.9 KB  |  613 lines

  1. /* This XAD client is written by Kyzer/CSG <kyzer@4u.net>, the original
  2.  * code was written by bzip's author, Julian Seward. bzip is (C) 1996
  3.  * Julian R. Seward.
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  */
  19.  
  20. /* $VER: bzip.c 1.1 (05.08.2000) */
  21.  
  22. #ifdef DEBUG
  23. void KPrintF(char *fmt, ...);
  24. #define D(x) { KPrintF x ; }
  25. #else
  26. #define D(x)
  27. #endif
  28.  
  29.  
  30. #include <exec/memory.h>
  31. #include <libraries/xadmaster.h>
  32. #include <proto/xadmaster.h>
  33. #include <string.h>
  34. #include "SDI_compiler.h"
  35.  
  36. #define XADBASE  REG(a6, struct xadMasterBase *xadMasterBase)
  37.  
  38. #ifndef XADMASTERFILE
  39. #define bzip_Client     FirstClient
  40. #define NEXTCLIENT      0
  41. const UBYTE version[] = "$VER: bzip 1.1 (05.08.2000)";
  42. #endif
  43. #define BZIP_VERSION    1
  44. #define BZIP_REVISION   1
  45.  
  46.  
  47. ASM(BOOL) bzip_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data), XADBASE) {
  48.   if (data[0] != 'B' || data[1] != 'Z' || data[2] != '0') return 0;
  49.   if (data[3] <  '1' || data[3] > '9') return 0;
  50.   return 1;
  51. }
  52.  
  53. /* there's only one file in a bzip archive - the uncompressed data */
  54. ASM(LONG) bzip_GetInfo(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  55.   struct TagItem tags[]  = {
  56.     { XAD_OBJNAMESIZE, 0 },
  57.     { TAG_DONE, 0 }
  58.   };
  59.  
  60.   struct TagItem datetags[] = {
  61.     { XAD_DATECURRENTTIME, 1 },
  62.     { XAD_GETDATEXADDATE,  0 },
  63.     { TAG_DONE, 0 }
  64.   };
  65.  
  66.   struct xadFileInfo *fi;
  67.   char *name;
  68.   int namelen;
  69.  
  70.   /* do we have a filename for this archive? */
  71.   if ((name = ai->xai_InName))
  72.     tags[0].ti_Data = namelen = strlen(name) + 1;
  73.  
  74.   if (!(ai->xai_FileInfo = fi = (struct xadFileInfo *) xadAllocObjectA(
  75.     XADOBJ_FILEINFO, (name) ? tags : NULL))) return XADERR_NOMEMORY;
  76.   fi->xfi_EntryNumber = 1;
  77.   fi->xfi_CrunchSize  = ai->xai_InSize - 4;
  78.   fi->xfi_Size        = 0;
  79.   fi->xfi_DataPos     = 3;
  80.   fi->xfi_Flags = XADFIF_NODATE | XADFIF_NOUNCRUNCHSIZE | XADFIF_SEEKDATAPOS;
  81.  
  82.   /* fill in today's date */
  83.   datetags[1].ti_Data = (ULONG) &fi->xfi_Date;
  84.   xadConvertDatesA(datetags);
  85.  
  86.   if (name) {
  87.     xadCopyMem(ai->xai_InName, (name = fi->xfi_FileName), namelen);
  88.     if (name[namelen-4] == '.'
  89.     && (name[namelen-3] == 'b' || name[namelen-3] == 'B')
  90.     && (name[namelen-2] == 'z' || name[namelen-2] == 'Z'))
  91.       name[namelen-4] = 0;
  92.   }
  93.   else {
  94.     fi->xfi_FileName = xadMasterBase->xmb_DefaultName;
  95.     fi->xfi_Flags   |= XADFIF_NOFILENAME;
  96.   }
  97.   return XADERR_OK;
  98. }
  99.  
  100.  
  101.  
  102. /* here begins the hard bit */
  103.  
  104. #define BZIP_READBUF_SIZE  512
  105. #define BZIP_OUTBUF_SIZE   4096
  106. #define BZIP_MAX_SYMBOLS   256
  107.  
  108. typedef 
  109.    struct {
  110.       ULONG  numScalings;
  111.       ULONG  numTraffic;
  112.       ULONG  totFreq;
  113.       ULONG  numSymbols;
  114.       ULONG  incValue;
  115.       ULONG  noExceed;
  116.       ULONG  freq[BZIP_MAX_SYMBOLS + 2];
  117.    }
  118.    Model;
  119.  
  120. struct BZIPstate {
  121.   struct xadMasterBase *xad;
  122.   struct xadArchiveInfo *ai;
  123.  
  124.   Model models[8], bogusModel;
  125.   ULONG bigL, bigR, bigD, bitsOutstanding;
  126.  
  127.   UBYTE readbuf[BZIP_READBUF_SIZE], *bufp, *bufend;
  128.   UBYTE outbuf[BZIP_OUTBUF_SIZE], *obufp, *obufend;
  129.   ULONG bitbuf;
  130.   UBYTE bitsleft;
  131.  
  132.   ULONG blocklen;      /* length of block */
  133.   UBYTE err;           /* error code */
  134.   UBYTE lastblock;     /* flag - is this the last block? */
  135.   ULONG crc;           /* CRC-so-far */
  136.   LONG  last, lastPP;  /* lastPP always = last + 1 */
  137.   LONG  origPtr;
  138.  
  139.   /* big memory areas */
  140.   UBYTE *block, *ll;
  141.   LONG *zptr;
  142. };
  143.  
  144. void bzip_fill_readbuf(struct BZIPstate *bzs) {
  145.   struct xadMasterBase *xadMasterBase = bzs->xad;
  146.   struct xadArchiveInfo *ai = bzs->ai;
  147.   ULONG avail = ai->xai_InSize - ai->xai_InPos;
  148.  
  149.   if (avail > BZIP_READBUF_SIZE) avail = BZIP_READBUF_SIZE;
  150.   bzs->bufend = (bzs->bufp = bzs->readbuf) + avail;
  151.   bzs->err = xadHookAccess(XADAC_READ, avail, (APTR)&bzs->readbuf, ai);
  152. }
  153.  
  154. #define ULONG_BITS (sizeof(ULONG)<<3)
  155. #define ENSURE_BITS(n) while (bzs->bitsleft < (n)) { \
  156.   if (bzs->bufp >= bzs->bufend) bzip_fill_readbuf(bzs); \
  157.   bzs->bitbuf |= *bzs->bufp++ << (ULONG_BITS-8 - bzs->bitsleft); \
  158.   bzs->bitsleft += 8; \
  159. }
  160. #define PEEK_BITS(n)   (bzs->bitbuf >> (ULONG_BITS - (n)))
  161. #define REMOVE_BITS(n) ((bzs->bitbuf <<= (n)), (bzs->bitsleft -= (n)))
  162. #define READ_BITS(v,n) {ENSURE_BITS(n); (v)=PEEK_BITS(n); REMOVE_BITS(n);}
  163.  
  164. ULONG bzip_crc32Table[256];
  165.  
  166. #define TWO_TO_THE(n)        (1 << (n))
  167. #define MAX_BITS_OUTSTANDING 500000000
  168.  
  169. #define smallB 26
  170. #define smallF 18
  171.  
  172. #define BASIS           0
  173. #define MODEL_2_3       1
  174. #define MODEL_4_7       2
  175. #define MODEL_8_15      3
  176. #define MODEL_16_31     4
  177. #define MODEL_32_63     5
  178. #define MODEL_64_127    6
  179. #define MODEL_128_255   7
  180.  
  181. void bzip_arithCodeStartDecoding (struct BZIPstate *bzs) {
  182.   bzs->bigL = 0;
  183.   bzs->bigR = TWO_TO_THE(smallB-1);
  184.   bzs->bigD = 0;
  185.   READ_BITS(bzs->bigD, smallB);
  186. }
  187.  
  188. LONG bzip_arithDecodeSymbol(struct BZIPstate *bzs, Model *m) {
  189.    ULONG smallL, smallH, smallT, smallR;
  190.    ULONG smallR_x_smallL, target, symbol;
  191.    ULONG bits, mybits;
  192.  
  193.    smallT = m->totFreq;
  194.  
  195.    /*--- Get target value. ---*/
  196.    smallR = bzs->bigR / smallT;
  197.    target = bzs->bigD / smallR;
  198.    if ((smallT-1) < target) target = smallT-1;
  199.  
  200.    symbol = 0;
  201.    smallH = 0;
  202.    while (smallH <= target) {
  203.       symbol++;
  204.       smallH += m->freq[symbol];
  205.    }
  206.    smallL = smallH - m->freq[symbol];
  207.  
  208.    smallR_x_smallL = smallR * smallL;
  209.    bzs->bigD -= smallR_x_smallL;
  210.    
  211.    if (smallH < smallT)
  212.       bzs->bigR = smallR * (smallH - smallL); else
  213.       bzs->bigR -= smallR_x_smallL;
  214.  
  215.    bits=0;
  216.    while ( bzs->bigR <= TWO_TO_THE ( smallB-2 ) ) {
  217.       bzs->bigR <<= 1; bits++;
  218.    }
  219.    bzs->bigD <<= bits;
  220.    READ_BITS(mybits, bits);
  221.    bzs->bigD |= mybits;
  222.    return (LONG)symbol;
  223. }
  224.  
  225. void bzip_initModel(
  226.   Model *m,
  227.   LONG initNumSymbols,
  228.   LONG initIncValue,
  229.   LONG initNoExceed
  230. ) {
  231.  
  232.   LONG i;
  233.   if (initIncValue == 0) {
  234.     m->totFreq = initNumSymbols;
  235.     for (i = 1; i <= initNumSymbols; i++) 
  236.       m->freq[i] = 1;
  237.   } else {
  238.     m->totFreq = initNumSymbols * initIncValue;
  239.     for (i = 1; i <= initNumSymbols; i++) 
  240.       m->freq[i] = initIncValue;
  241.   };
  242.  
  243.   m->numSymbols                = initNumSymbols;
  244.   m->incValue                  = initIncValue;
  245.   m->noExceed                  = initNoExceed;
  246.   m->freq[0]                   = 0;
  247.   m->freq[initNumSymbols + 1]  = 0;
  248.   m->numScalings               = 0;
  249. }
  250.  
  251.  
  252. void bzip_updateModel(Model *m, LONG symbol) {
  253.   ULONG i;
  254.   m->totFreq      += m->incValue;
  255.   m->freq[symbol] += m->incValue;
  256.   if (m->totFreq > m->noExceed) {
  257.     m->totFreq = 0;
  258.     m->numScalings++;
  259.     for (i = 1; i <= m->numSymbols; i++) {
  260.       m->freq[i] = (m->freq[i] + 1) >> 1;
  261.       m->totFreq += m->freq[i];
  262.     }
  263.   }
  264. }
  265.  
  266. LONG bzip_getSymbol(struct BZIPstate *bzs, Model *m) {
  267.   LONG symbol = bzip_arithDecodeSymbol(bzs, m);
  268.   bzip_updateModel(m, symbol);
  269.   return symbol;
  270. }
  271.  
  272. void bzip_initBogusModel(struct BZIPstate *bzs) {
  273.   bzip_initModel(&bzs->bogusModel, 256, 0, 256);
  274. }
  275.  
  276. UBYTE bzip_getUBYTE(struct BZIPstate *bzs) {
  277.   return (UBYTE) (bzip_getSymbol(bzs, &bzs->bogusModel) - 1);
  278. }
  279.  
  280.  
  281. LONG bzip_getLONG(struct BZIPstate *bzs) {
  282.   ULONG x = 
  283.      (bzip_getUBYTE(bzs) << 24)
  284.    | (bzip_getUBYTE(bzs) << 16)
  285.    | (bzip_getUBYTE(bzs) <<  8)
  286.    | (bzip_getUBYTE(bzs)      );
  287.   return (LONG) x;
  288. }
  289.  
  290. ULONG bzip_getULONG(struct BZIPstate *bzs) {
  291.   return
  292.      (bzip_getUBYTE(bzs) << 24)
  293.    | (bzip_getUBYTE(bzs) << 16)
  294.    | (bzip_getUBYTE(bzs) <<  8)
  295.    | (bzip_getUBYTE(bzs)      );
  296. }
  297.  
  298.  
  299. void bzip_initModels(struct BZIPstate *bzs) {
  300.   bzip_initModel(&bzs->models[BASIS],         11,  12,  1000);
  301.   bzip_initModel(&bzs->models[MODEL_2_3],     2,   4,   1000);
  302.   bzip_initModel(&bzs->models[MODEL_4_7],     4,   3,   1000);
  303.   bzip_initModel(&bzs->models[MODEL_8_15],    8,   3,   1000);
  304.   bzip_initModel(&bzs->models[MODEL_16_31],   16,  3,   1000);
  305.   bzip_initModel(&bzs->models[MODEL_32_63],   32,  3,   1000);
  306.   bzip_initModel(&bzs->models[MODEL_64_127],  64,  2,   1000);
  307.   bzip_initModel(&bzs->models[MODEL_128_255], 128, 1,   1000);
  308. }
  309.  
  310.  
  311. #define VAL_RUNA     1
  312. #define VAL_RUNB     2
  313. #define VAL_ONE      3
  314. #define VAL_2_3      4
  315. #define VAL_4_7      5
  316. #define VAL_8_15     6
  317. #define VAL_16_31    7
  318. #define VAL_32_63    8
  319. #define VAL_64_127   9
  320. #define VAL_128_255  10
  321. #define VAL_EOB      11
  322.  
  323. #define RUNA    257
  324. #define RUNB    258
  325. #define EOB     259
  326. #define INVALID 260
  327.  
  328. LONG bzip_getMTFVal(struct BZIPstate *bzs) {
  329.   switch (bzip_getSymbol(bzs, &bzs->models[BASIS])) {
  330.   case VAL_EOB:    return EOB;
  331.   case VAL_RUNA:   return RUNA;
  332.   case VAL_RUNB:   return RUNB;
  333.   case VAL_ONE:    return 1;
  334.   case VAL_2_3:    return bzip_getSymbol(bzs, &bzs->models[MODEL_2_3])+2-1;
  335.   case VAL_4_7:    return bzip_getSymbol(bzs, &bzs->models[MODEL_4_7])+4-1;
  336.   case VAL_8_15:   return bzip_getSymbol(bzs, &bzs->models[MODEL_8_15])+8-1;
  337.   case VAL_16_31:  return bzip_getSymbol(bzs, &bzs->models[MODEL_16_31])+16-1;
  338.   case VAL_32_63:  return bzip_getSymbol(bzs, &bzs->models[MODEL_32_63])+32-1;
  339.   case VAL_64_127: return bzip_getSymbol(bzs, &bzs->models[MODEL_64_127])+64-1;
  340.   }
  341.   return (LONG) bzip_getSymbol(bzs, &bzs->models[MODEL_128_255]) + 128 - 1;
  342. }
  343.  
  344. void bzip_getAndMoveToFrontDecode(struct BZIPstate *bzs) {
  345.    UBYTE  yy[256];
  346.    LONG  i, j, tmpOrigPtr, nextSym, limit;
  347.  
  348.    limit = bzs->blocklen;
  349.  
  350.    tmpOrigPtr = bzip_getLONG(bzs);
  351.    if (tmpOrigPtr < 0) 
  352.       bzs->origPtr = ( -tmpOrigPtr ) - 1; else
  353.       bzs->origPtr =    tmpOrigPtr   - 1;
  354.  
  355.    bzip_initModels(bzs);
  356.  
  357.    for (i = 0; i <= 255; i++)
  358.       yy[i] = (UBYTE) i;
  359.    
  360.    bzs->last = -1;
  361.  
  362.    nextSym = bzip_getMTFVal(bzs);
  363.  
  364.    LOOPSTART:
  365.  
  366.    if (nextSym == EOB) { bzs->lastblock = (tmpOrigPtr < 0); return; }
  367.  
  368.    /*--- acquire run-length bits, most significant first ---*/
  369.    if (nextSym == RUNA || nextSym == RUNB) {
  370.       LONG n = 0;
  371.       do {
  372.          n <<= 1;
  373.          if (nextSym == RUNA) n |= 1;
  374.          n++;
  375.          nextSym = bzip_getMTFVal(bzs);
  376.       } while (nextSym == RUNA || nextSym == RUNB);
  377.  
  378.       while (n > 0) {
  379.          bzs->last++;
  380.          if (bzs->last >= limit) { bzs->err = XADERR_OUTPUT; return; }
  381.          bzs->ll[bzs->last] = yy[0];
  382.          n--;
  383.       }
  384.       goto LOOPSTART;
  385.    }
  386.  
  387.    if (nextSym >= 1 && nextSym <= 255) {
  388.          bzs->last++;
  389.          if (bzs->last >= limit) { bzs->err = XADERR_OUTPUT; return; }
  390.          bzs->ll[bzs->last] = yy[nextSym];
  391.  
  392.       /*--
  393.          This loop is hammered during decompression,
  394.          hence the unrolling.
  395.  
  396.          for (j = nextSym; j > 0; j--) yy[j] = yy[j-1];
  397.       --*/
  398.  
  399.       j = nextSym;
  400.       for (; j > 3; j -= 4) {
  401.          yy[j]   = yy[j-1]; 
  402.          yy[j-1] = yy[j-2];
  403.          yy[j-2] = yy[j-3];
  404.          yy[j-3] = yy[j-4];
  405.       }
  406.       for (; j > 0; j--) yy[j] = yy[j-1];
  407.  
  408.       yy[0] = bzs->ll[bzs->last];
  409.       nextSym = bzip_getMTFVal(bzs);
  410.       goto LOOPSTART;
  411.    }
  412.  
  413.    bzs->err = XADERR_ILLEGALDATA;
  414.    return;
  415. }
  416.  
  417. void bzip_undoReversibleTransformation(struct BZIPstate *bzs) {
  418.   UBYTE *block = bzs->block, *ll = bzs->ll;
  419.   LONG  cc[256], *zptr = bzs->zptr;
  420.   LONG  i, j, ch, sum;
  421.  
  422.   for (i = 0; i <= 255; i++) cc[i] = 0;
  423.    
  424.   for (i = 0; i <= bzs->last; i++) {
  425.     UBYTE ll_i = ll[i];
  426.     zptr[i] = cc[ll_i];
  427.     cc[ll_i] ++;
  428.   }
  429.  
  430.   sum = 0;
  431.   for (ch = 0; ch <= 255; ch++) {
  432.     sum = sum + cc[ch];
  433.     cc[ch] = sum - cc[ch];
  434.   }
  435.  
  436.   i = bzs->origPtr;
  437.   for (j = bzs->last; j >= 0; j--) {
  438.     UBYTE ll_i = ll[i];
  439.     block[j] = ll_i;
  440.     i = zptr[i] + cc[ll_i];
  441.   }
  442. }
  443.  
  444. #define SPOT_BASIS_STEP 8000
  445.  
  446. void bzip_spotBlock (struct BZIPstate *bzs) {
  447.   LONG pos, delta, newdelta;
  448.   UBYTE *block = bzs->block;
  449.  
  450.   pos   = SPOT_BASIS_STEP;
  451.   delta = 1;
  452.  
  453.   while (pos < bzs->last) {
  454.     LONG n = (LONG) block[pos] - 1;
  455.          if (n == 256) n = 0;
  456.     else if (n == -1)  n = 255;
  457.  
  458.     if (n < 0 || n > 255) {
  459.        bzs->err = XADERR_ILLEGALDATA;
  460.        return;
  461.     }
  462.  
  463.     block[pos] = (UBYTE)n;
  464.     switch (delta) {
  465.     case 3:  newdelta = 1; break;
  466.     case 1:  newdelta = 4; break;
  467.     case 4:  newdelta = 5; break;
  468.     case 5:  newdelta = 9; break;
  469.     case 9:  newdelta = 2; break;
  470.     case 2:  newdelta = 6; break;
  471.     case 6:  newdelta = 7; break;
  472.     case 8:  newdelta = 8; break;
  473.     case 7:  newdelta = 3; break;
  474.     default: newdelta = 1; break;
  475.     }
  476.     delta = newdelta;
  477.     pos = pos + SPOT_BASIS_STEP + 17 * (newdelta - 5);
  478.   }
  479.  
  480.  
  481. #define OUTPUT_BYTE(byte) do { \
  482.   if (bzs->obufp >= bzs->obufend) { \
  483.     if ((bzs->err = xadHookAccess(XADAC_WRITE, BZIP_OUTBUF_SIZE, \
  484.     (APTR) bzs->outbuf, ai))) return; \
  485.     bzs->obufp = bzs->outbuf; \
  486.   } \
  487.   *bzs->obufp++ = (byte); \
  488.   crc = (crc<<8) ^ bzip_crc32Table[(crc>>24) ^ ((byte) & 0xFF)]; \
  489. } while(0)
  490.  
  491.  
  492. void bzip_unRLEandDump(struct BZIPstate *bzs) {
  493.   struct xadMasterBase *xadMasterBase = bzs->xad;
  494.   struct xadArchiveInfo *ai = bzs->ai;
  495.   UBYTE *block = bzs->block;
  496.   ULONG crc = bzs->crc;
  497.  
  498.   LONG  i = 0, j, numbytes = bzs->last, count = 0, chPrev, ch = 256;
  499.   UBYTE c;
  500.  
  501.   if (bzs->lastblock) numbytes--;
  502.  
  503.   while (i <= numbytes) {
  504.     chPrev = ch;
  505.     ch = block[i];
  506.     i++;
  507.  
  508.     c = (UBYTE) ch;
  509.     OUTPUT_BYTE(c);
  510.     if (ch != chPrev) {
  511.       count = 1;
  512.     } else {
  513.       count++;
  514.       if (count >= 4) {
  515.         c = (UBYTE) ch;
  516.         j = block[i];
  517.         while (j--) OUTPUT_BYTE(c);
  518.         i++;
  519.         count = 0;
  520.       }
  521.     }
  522.   }
  523.  
  524.   bzs->crc = crc;
  525.   if (bzs->lastblock && block[bzs->last] != 42)
  526.     bzs->err = XADERR_ILLEGALDATA;
  527. }
  528.  
  529.  
  530. void bzip_MakeCRC32R(ULONG *buf, ULONG ID) {
  531.   ULONG k;
  532.   int i, j;
  533.   for(i = 0; i < 256; i++) {
  534.     k = i << 24;
  535.     for(j=8; j--;) k = (k & 0x80000000) ? ((k << 1) ^ ID) : (k << 1);
  536.     buf[i] = k;
  537.   }
  538. }
  539.  
  540. #define ERROR(error) { bzs->err = XADERR_##error; goto exit_handler; }
  541. #define ALLOC(t,v,l) if (!((v) = (t) xadAllocVec((l),0))) ERROR(NOMEMORY)
  542. #define FREE(x) xadFreeObjectA((x), NULL)
  543.  
  544. ASM(LONG) bzip_UnArchive(REG(a0, struct xadArchiveInfo *ai), XADBASE) {
  545.   struct BZIPstate *bzs;
  546.   UBYTE sizechar;
  547.   LONG err;
  548.  
  549.   bzs = xadAllocVec(sizeof(struct BZIPstate), 0);
  550.   if (!bzs) { err = XADERR_NOMEMORY; goto exit_handler; }
  551.  
  552.   bzs->ai        = ai;
  553.   bzs->xad       = xadMasterBase;
  554.   bzs->crc       = 0xFFFFFFFF;
  555.   bzs->bitbuf    = 0;
  556.   bzs->bitsleft  = 0;
  557.   bzs->lastblock = 0;
  558.   bzs->err       = XADERR_OK;
  559.   bzs->block     = NULL;
  560.   bzs->ll        = NULL;
  561.   bzs->zptr      = NULL;
  562.   bzs->obufp     = bzs->outbuf;
  563.   bzs->obufend   = bzs->outbuf + BZIP_OUTBUF_SIZE;
  564.  
  565.   if ((bzs->err = xadHookAccess(XADAC_READ, 1, (APTR)&sizechar, ai)))
  566.     goto exit_handler;
  567.   if (sizechar < '1' || sizechar > '9') ERROR(DATAFORMAT);
  568.  
  569.   bzs->blocklen = 100000 * (sizechar - '0');
  570.   ALLOC(UBYTE *, bzs->block, bzs->blocklen * sizeof(UBYTE));
  571.   ALLOC(UBYTE *, bzs->ll,    bzs->blocklen * sizeof(UBYTE));
  572.   ALLOC(LONG *,  bzs->zptr,  bzs->blocklen * sizeof(LONG));
  573.  
  574.   bzip_MakeCRC32R(bzip_crc32Table, 0x04C11DB7);
  575.   bzip_initBogusModel(bzs);
  576.   bzip_arithCodeStartDecoding(bzs);
  577.   do {
  578.     if (bzs->err) goto exit_handler; bzip_getAndMoveToFrontDecode(bzs);
  579.     if (bzs->err) goto exit_handler; bzip_undoReversibleTransformation(bzs);
  580.     if (bzs->err) goto exit_handler; bzip_spotBlock(bzs);
  581.     if (bzs->err) goto exit_handler; bzip_unRLEandDump(bzs);
  582.   } while (!bzs->lastblock);
  583.  
  584.   /* write any remaining bytes */
  585.   if (bzs->obufp > bzs->outbuf) {
  586.     if ((bzs->err = xadHookAccess(XADAC_WRITE, bzs->obufp - bzs->outbuf,
  587.       (APTR) bzs->outbuf, ai))) goto exit_handler;
  588.   }
  589.  
  590.   if ((!bzs->err) && (bzip_getULONG(bzs) != (~(bzs->crc)))) ERROR(CHECKSUM);
  591.   
  592. exit_handler:
  593.   if (bzs) {
  594.     err = bzs->err;
  595.     if (bzs->block) FREE(bzs->block);
  596.     if (bzs->ll)    FREE(bzs->ll);
  597.     if (bzs->zptr)  FREE(bzs->zptr);
  598.     FREE(bzs);
  599.   }
  600.   return err;
  601. }
  602.  
  603.  
  604. const struct xadClient bzip_Client = {
  605.   NEXTCLIENT, XADCLIENT_VERSION, 7, BZIP_VERSION, BZIP_REVISION,
  606.   4, XADCF_FILEARCHIVER | XADCF_FREEFILEINFO, 0, "BZip",
  607.   (BOOL (*)()) bzip_RecogData,
  608.   (LONG (*)()) bzip_GetInfo,
  609.   (LONG (*)()) bzip_UnArchive,
  610.   NULL
  611. };
  612.